﻿// -------------------------------------------------------------------------------------------------------
// LICENSE INFORMATION
//
// - This software is licensed under the MIT shared source license.
// - The "official" source code for this project is maintained at http://mtcagent.codeplex.com
//
// Copyright (c) 2010 OpenNETCF Consulting
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
// associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial 
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
// -------------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.Web;
using System.Diagnostics;
using OpenNETCF.IoC;
using System.Xml.Linq;
using System.Threading;

namespace OpenNETCF.MTConnect
{
    public partial class VirtualAgentHandler
    {
        private void HandlePut(HttpContext context)
        {
            var segments = GetRequestPathSegments(context);

            switch (segments.Length)
            {
                case 0:
                    HandleAgentCommand(context);
                    return;
                case 2:
                    if (string.Compare(segments[0], "adapters", true) == 0)
                    {
                        HandleAdapterCommand(context, segments[1]);
                        return;
                    }
                    break;
            }

            throw new HttpException(HttpErrorCode.MethodNotAllowed, "Unsupported PUT");
        }

        private void HandleAdapterCommand(HttpContext context, string adapterID)
        {
            var request = GetRequestData(context);
            var doc = XDocument.Parse(request);

            // look for call method
            var commandNode = doc.Elements(XmlNodeName.CallMethod).FirstOrDefault();

            if (commandNode != null)
            {
                ProcessCallMethod(context, adapterID, commandNode);
            }
        }

        private void ProcessCallMethod(HttpContext context, string adapterID, XElement methodNode)
        {
            var methodName = methodNode.Attribute(XmlAttributeName.MethodName).Value;

            List<string> parameters = new List<string>();

            foreach(var paramNode in methodNode.Elements(XmlNodeName.Parameter))
            {
                var paramName = paramNode.Attribute(XmlAttributeName.Name).Value;
                var paramValue = paramNode.Value;

                parameters.Add(paramValue);
            }

            string result = HostedAdapterService.CallAdapterMethod(adapterID, methodName, parameters.ToArray());

            // return result
            var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"));

            var element = new XElement(XmlNodeName.ReturnValue,
                new XAttribute(XmlAttributeName.Type, result == null ? "null" : result.GetType().Name));

            if(result != null)
            {
                element.Value = result;
            }

            doc.Add(element);

            context.Response.ContentType = "text/xml";
            context.Response.Write(doc.ToString(true));
        }

        private void HandleAgentCommand(HttpContext context)
        {
            var request = GetRequestData(context);
            var doc = XDocument.Parse(request);

            // look for a command
            var commands = doc.Elements(XmlNodeName.VirtualAgentCommand);

            if (commands == null) throw new Exception("Invalid PUT data");

            foreach (var command in commands)
            {
                var cmd = command.Attribute(XmlAttributeName.Command).Value;
                // todo: add support for parameters

                switch (cmd.ToLower())
                {
                    case "restart":
                        // do this on a background thread so the caller can get a result
                        new Thread(new ThreadStart(delegate
                            {
                                Thread.Sleep(1000);
                                RestartRequested.Fire(this, EventArgs.Empty);
                            })) { IsBackground = true }
                        .Start();

                        // TODO: make this return data match the spec
                        context.Response.Write("ok");
                        break;
                    default:
                        throw new Exception("Unsupported command");
                }
            }
        }
    }
}
